#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#include <dirent.h>
#include "../common/clog.h"
#include "../common/config.h"
#include "../common/common.h"

// 日志文件结构
typedef struct {
    char process_name[MAX_PROCESS_NAME_LEN];
    FILE* file;
    long current_size;
    char* buffer;               // 文件缓存
    int buffer_size;
    int buffer_used;
    time_t last_flush;
} log_file_t;

typedef struct client_info {
    int socket;
    struct sockaddr_un addr;
    struct client_info* next;
} client_info_t;

static int server_socket = -1;
static client_info_t* clients = NULL;
static log_file_t log_files[MAX_LOG_FILES];
static int log_file_count = 0;
static log_config_t server_config;
static pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER;

// 函数声明
void cleanup_server(void);
void signal_handler(int sig);
void* client_handler(void* arg);
log_file_t* get_or_create_log_file(const char* process_name);
void rotate_log_file(log_file_t* log_file);
void archive_log_file(const char* old_path, const char* process_name);
void flush_log_file(log_file_t* log_file);
void* flush_thread(void* arg);

// 刷新日志文件缓存
void flush_log_file(log_file_t* log_file) {
    if (log_file->buffer_used > 0) {
        fwrite(log_file->buffer, 1, log_file->buffer_used, log_file->file);
        fflush(log_file->file);
        log_file->current_size += log_file->buffer_used;
        log_file->buffer_used = 0;
        log_file->last_flush = time(NULL);
    }
}

// 定期刷新线程
void* flush_thread(void* arg) {
    (void)arg; // 避免未使用参数警告
    
    while (1) {
        sleep(server_config.flush_interval);
        
        pthread_mutex_lock(&file_mutex);
        for (int i = 0; i < log_file_count; i++) {
            if (log_files[i].file && 
                (time(NULL) - log_files[i].last_flush) >= server_config.flush_interval) {
                flush_log_file(&log_files[i]);
            }
        }
        pthread_mutex_unlock(&file_mutex);
    }
    
    return NULL;
}

void cleanup_server(void) {
    printf("Cleaning up server...\n");
    
    // 关闭所有日志文件
    pthread_mutex_lock(&file_mutex);
    for (int i = 0; i < log_file_count; i++) {
        if (log_files[i].file) {
            flush_log_file(&log_files[i]); // 刷新缓存
            fclose(log_files[i].file);
            if (log_files[i].buffer) {
                free(log_files[i].buffer);
            }
        }
    }
    pthread_mutex_unlock(&file_mutex);
    
    // 关闭所有客户端连接
    client_info_t* current = clients;
    while (current) {
        close(current->socket);
        client_info_t* next = current->next;
        free(current);
        current = next;
    }
    
    // 关闭服务器socket
    if (server_socket != -1) {
        close(server_socket);
        unlink(server_config.socket_path);
    }
    
    pthread_mutex_destroy(&file_mutex);
}

void signal_handler(int sig) {
    printf("Received signal %d, shutting down server...\n", sig);
    cleanup_server();
    exit(0);
}

log_file_t* get_or_create_log_file(const char* process_name) {
    // 查找现有文件
    for (int i = 0; i < log_file_count; i++) {
        if (strcmp(log_files[i].process_name, process_name) == 0) {
            return &log_files[i];
        }
    }
    
    // 创建新文件
    if (log_file_count >= MAX_LOG_FILES) {
        fprintf(stderr, "Too many log files\n");
        return NULL;
    }
    
    log_file_t* log_file = &log_files[log_file_count++];
    strcpy(log_file->process_name, process_name);
    
    // 分配文件缓存
    log_file->buffer_size = server_config.buffer_size;
    log_file->buffer = malloc(log_file->buffer_size);
    if (!log_file->buffer) {
        fprintf(stderr, "Failed to allocate buffer for log file\n");
        log_file_count--;
        return NULL;
    }
    log_file->buffer_used = 0;
    log_file->last_flush = time(NULL);
    
    // 构建文件路径
    char file_path[512];
    char filename[128];
    snprintf(filename, sizeof(filename), "%s.log", process_name);
    
    if (build_file_path(file_path, sizeof(file_path), server_config.log_path, filename) != 0) {
        fprintf(stderr, "Failed to build file path\n");
        free(log_file->buffer);
        log_file_count--;
        return NULL;
    }
    
    log_file->file = fopen(file_path, "a");
    if (!log_file->file) {
        fprintf(stderr, "Failed to open log file: %s\n", file_path);
        free(log_file->buffer);
        log_file_count--;
        return NULL;
    }
    
    // 获取当前文件大小
    fseek(log_file->file, 0, SEEK_END);
    log_file->current_size = ftell(log_file->file);
    
    return log_file;
}

void archive_log_file(const char* old_path, const char* process_name) {
    time_t now = time(NULL);
    struct tm* tm_info = localtime(&now);
    
    char timestamp[32];
    strftime(timestamp, sizeof(timestamp), "%Y%m%d%H%M%S", tm_info);
    
    char tar_path[512];
    snprintf(tar_path, sizeof(tar_path), "%s/%s_%s.tar.gz", 
             server_config.log_path, process_name, timestamp);
    
    // 使用tar命令压缩文件
    char command[1024];
    snprintf(command, sizeof(command), "tar -czf %s -C %s %s.log", 
             tar_path, server_config.log_path, process_name);
    
    int result = system(command);
    if (result == 0) {
        printf("Log file archived: %s\n", tar_path);
        // 删除原文件
        unlink(old_path);
    } else {
        fprintf(stderr, "Failed to archive log file\n");
    }
}

void rotate_log_file(log_file_t* log_file) {
    if (log_file->current_size < server_config.max_file_size) {
        return;
    }
    
    // 关闭当前文件
    fclose(log_file->file);
    
    // 构建文件路径
    char file_path[512];
    snprintf(file_path, sizeof(file_path), "%s/%s.log", 
             server_config.log_path, log_file->process_name);
    
    // 压缩旧文件
    archive_log_file(file_path, log_file->process_name);
    
    // 创建新文件
    log_file->file = fopen(file_path, "w");
    if (!log_file->file) {
        fprintf(stderr, "Failed to create new log file: %s\n", file_path);
        return;
    }
    
    // 重新分配缓存
    if (log_file->buffer) {
        free(log_file->buffer);
    }
    log_file->buffer = malloc(server_config.buffer_size);
    if (!log_file->buffer) {
        fprintf(stderr, "Failed to allocate buffer for new log file\n");
        return;
    }
    log_file->buffer_size = server_config.buffer_size;
    log_file->buffer_used = 0;
    log_file->current_size = 0;
    log_file->last_flush = time(NULL);
    printf("Log file rotated for process: %s\n", log_file->process_name);
}

void* client_handler(void* arg) {
    int client_socket = *(int*)arg;
    free(arg);
    
    log_message_t msg;
    while (1) {
        ssize_t received = recv(client_socket, &msg, sizeof(msg), 0);
        if (received <= 0) {
            break;
        }
        
        // 检查日志级别过滤
        if (!should_log_level(msg.level, server_config.min_log_level)) {
            continue; // 忽略低级别日志
        }
        
        pthread_mutex_lock(&file_mutex);
        
        // 获取或创建日志文件
        log_file_t* log_file = get_or_create_log_file(msg.process_name);
        if (log_file && log_file->file) {
            // 格式化日志行
            char log_line[1024];
            int log_len = format_log_line(log_line, sizeof(log_line), &msg);
            
            if (log_len > 0) {
                // 检查缓存是否足够
                if (log_file->buffer_used + log_len > log_file->buffer_size) {
                    flush_log_file(log_file); // 刷新缓存
                }
                
                // 添加到缓存
                memcpy(log_file->buffer + log_file->buffer_used, log_line, log_len);
                log_file->buffer_used += log_len;
                
                // 检查是否需要轮转
                if (log_file->current_size + log_file->buffer_used >= server_config.max_file_size) {
                    flush_log_file(log_file);
                    rotate_log_file(log_file);
                }
            }
        }
        
        pthread_mutex_unlock(&file_mutex);
    }
    
    close(client_socket);
    return NULL;
}

// 检查是否已有服务器实例在运行
int check_server_running(const char* socket_path) {
    int test_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    if (test_socket == -1) {
        return 0; // 无法创建socket，假设没有运行
    }
    
    struct sockaddr_un test_addr;
    memset(&test_addr, 0, sizeof(test_addr));
    test_addr.sun_family = AF_UNIX;
    strcpy(test_addr.sun_path, socket_path);
    
    // 尝试连接到现有的服务器
    int result = connect(test_socket, (struct sockaddr*)&test_addr, sizeof(test_addr));
    close(test_socket);
    
    return (result == 0) ? 1 : 0; // 连接成功说明服务器在运行
}

int main() {
    // 加载配置
    if (load_log_config("log_config.conf", &server_config) != 0) {
        fprintf(stderr, "Failed to load config\n");
        return 1;
    }
    
    // 检查是否已有服务器实例在运行
    if (check_server_running(server_config.socket_path)) {
        printf("Log server is already running on %s\n", server_config.socket_path);
        printf("Only one instance is allowed. Exiting...\n");
        return 0;
    }
    
    // 创建日志目录（支持递归创建）
    if (create_directory_recursive(server_config.log_path) != 0) {
        perror("Failed to create log directory");
        return 1;
    }
    
    // 设置信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // 创建Unix domain socket
    server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("socket creation failed");
        return 1;
    }
    
    struct sockaddr_un server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sun_family = AF_UNIX;
    strcpy(server_addr.sun_path, server_config.socket_path);
    
    // 删除可能存在的旧socket文件
    unlink(server_config.socket_path);
    
    // 绑定socket
    if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
        perror("bind failed");
        close(server_socket);
        return 1;
    }
    
    // 监听连接
    if (listen(server_socket, 10) == -1) {
        perror("listen failed");
        close(server_socket);
        return 1;
    }
    
    printf("Log server started, listening on %s\n", server_config.socket_path);
    printf("Log directory: %s\n", server_config.log_path);
    printf("Max file size: %ld bytes\n", server_config.max_file_size);
    printf("Min log level: %s\n", get_level_string(server_config.min_log_level));
    printf("Buffer size: %d bytes\n", server_config.buffer_size);
    printf("Flush interval: %d seconds\n", server_config.flush_interval);
    printf("Console output: %s\n", server_config.console_output ? "enabled" : "disabled");
    
    // 启动定期刷新线程
    pthread_t flush_tid;
    if (pthread_create(&flush_tid, NULL, flush_thread, NULL) != 0) {
        perror("Failed to create flush thread");
        return 1;
    }
    pthread_detach(flush_tid);
    
    // 接受客户端连接
    while (1) {
        struct sockaddr_un client_addr;
        socklen_t client_len = sizeof(client_addr);
        
        int client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_len);
        if (client_socket == -1) {
            perror("accept failed");
            continue;
        }
        
        printf("New client connected\n");
        
        // 创建线程处理客户端
        pthread_t thread;
        int* socket_ptr = malloc(sizeof(int));
        *socket_ptr = client_socket;
        
        if (pthread_create(&thread, NULL, client_handler, socket_ptr) != 0) {
            perror("pthread_create failed");
            close(client_socket);
            free(socket_ptr);
        } else {
            pthread_detach(thread);
        }
    }
    
    cleanup_server();
    return 0;
}
